#include "application.h"

#define C_AUDIO_DECODE_STACK_SIZE	512
#define C_AUDIO_Q_ACCEPT_MAX		5

/*os task stack */
INT32U		audio_decode_stack[C_AUDIO_DECODE_STACK_SIZE];

/* os task queue */
OS_EVENT	*aud_dec_q;
OS_EVENT	*aud_dec_ack_m;

void		*aud_dec_q_buffer[C_AUDIO_Q_ACCEPT_MAX];

/* audio decoder api*/
static INT32S (*pfun_decode_one_frame) (INT16S *);
static INT32S	aud_dec_special_effect_start(void);
static void		aud_dec_special_effect_stop(void);

static INT32S	aud_dec_wave_init(void);
static INT32S	aud_dec_wave_one_frame(INT16S *pcm_buffer_addr);

#if VOICE_CHANGER_EN || UP_SAMPLE_EN
static INT32S	aud_dec_wave_one_output(void *work_mem, INT16S *pcm_buffer_addr, INT32S maxlen);
#endif


#if VOICE_CHANGER_EN == 1
static INT32S (*pfnVcOutput) (void *, INT16S *, INT32S);
#elif UP_SAMPLE_EN == 1
static INT32S (*pfnUsOutput) (void *, INT16S *, INT32S);
#endif
INT32S audio_decode_task_start(void)
{
	INT32S	nRet;
	nRet = STATUS_OK;
	POST_MESSAGE(aud_dec_q, MSG_AUD_DEC_START, aud_dec_ack_m, 5000);

	// audio start play
	if(p_vid_dec_para->upsample_flag)
		aud_dec_dac_start(p_vid_dec_para->aud_dec_ch_no, p_vid_dec_para->aud_dec_sr);
	else
		aud_dec_dac_start(p_wave_info->nChannels, p_wave_info->nSamplesPerSec);
Return:
	return nRet;
}

INT32S audio_decode_task_stop(void)
{
	INT32S	nRet;

	nRet = STATUS_OK;
	POST_MESSAGE(aud_dec_q, MSG_AUD_DEC_STOP, aud_dec_ack_m, 5000);
Return:
	return nRet;
}

INT32S audio_decode_task_pause(void)
{
	aud_dec_dac_stop();

	#if DRV_l1_DAC_ON_OFF
	R_DAC_CHA_CTRL &= ~(1 << 13);
	R_DAC_CHB_CTRL &= ~(1 << 13);
	#endif

	return 0;
}

INT32S audio_decode_task_resume(void)
{
	if(p_vid_dec_para->upsample_flag)
	{
		aud_dec_dac_start(p_vid_dec_para->aud_dec_ch_no, p_vid_dec_para->aud_dec_sr);
	}
	else
	{
		aud_dec_dac_start(p_wave_info->nChannels, p_wave_info->nSamplesPerSec);
	}

	#if DRV_l1_DAC_ON_OFF
	R_DAC_CHA_CTRL |= (1 << 13);
	R_DAC_CHB_CTRL |= (1 << 13);
	#endif

	return 0;
}

INT32S audio_decode_task_create(INT8U prio)
{
	INT8U	err;
	INT32S	nRet;

	DBG_PRINT("%s ... \r\n", __func__);

	aud_dec_q = OSQCreate(aud_dec_q_buffer, C_AUDIO_Q_ACCEPT_MAX);
	if(!aud_dec_q)
		RETURN(STATUS_FAIL);

	aud_dec_ack_m = OSMboxCreate(NULL);
	if(!aud_dec_ack_m)
		RETURN(STATUS_FAIL);

	err = OSTaskCreate(audio_decode_task_entry, NULL, (void *) &audio_decode_stack[C_AUDIO_DECODE_STACK_SIZE - 1], prio);
	if(err != OS_NO_ERR)
		RETURN(STATUS_FAIL);


	nRet = STATUS_OK;
Return:
	return nRet;
}

INT32S audio_decode_task_del(INT8U prio)
{
	INT8U	err;
	INT32S	nRet;

	//POST_MESSAGE(aud_dec_q, MSG_AUD_DEC_EXIT, aud_dec_ack_m, 5000);
	//----del video decode  task here , save waiting ack time
	OSTaskSuspend(prio);
	OSTimeDly(1);
	OSTaskDelReq(prio);
	OSTaskDel(prio);

	nRet = STATUS_OK;
//Return:
	OSQFlush(aud_dec_q);
	OSQDel(aud_dec_q, OS_DEL_ALWAYS, &err);
	OSMboxDel(aud_dec_ack_m, 0, &err);

	return nRet;
}

void audio_decode_task_end(void)
{
	aud_dec_dac_stop();
	aud_dec_double_buffer_free();
	vid_dec_aud_dec_memory_free();
}

void audio_decode_task_entry(void *param)
{
	OS_INIT_CRITICAL();

	INT8U	err;
	INT32S	cwlen, nRet, buf_RI, buf_WI;
	INT32U	i, msg_id, pcm_addr;
	INT64S	delta_ta[AUDIO_FRAME_NO];

	DBG_PRINT("%s ... \r\n", __func__);

	while(1)
	{
		msg_id = (INT32U) OSQPend(aud_dec_q, 0, &err);
		if(err != OS_NO_ERR)
			continue;

		switch(msg_id)
		{
		case MSG_AUD_DEC_DMA_DONE:
			//set buffer
			aud_dec_double_buffer_set((INT16U *) pcm_addr, cwlen);

			// increase audio time
			OS_ENTER_CRITICAL();
			p_vid_dec_para->ta += delta_ta[buf_RI];
			OS_EXIT_CRITICAL();

			buf_RI++;
			if(buf_RI >= AUDIO_FRAME_NO)
				buf_RI -= AUDIO_FRAME_NO;

			//decoder next buffer
			pcm_addr = vid_dec_get_next_aud_buffer();
			cache_invalid_range( (INT32U)(p_vid_dec_para->ring_buffer_addr),(INT32U)(p_vid_dec_para->ring_buffer_size));
			cwlen = pfun_decode_one_frame((INT16S *) pcm_addr);
			if(cwlen <= 0)
			{
				//check audio end
				if(MultiMediaParser_IsEOA(p_vid_dec_para->media_handle))
				{
					if(aud_dec_dma_status_get() == 0)
					{
						if(vid_dec_get_status() & C_AUDIO_DECODE_PLAYING)
						{
							DBG_PRINT("AudDecEnd.\r\n");
							audio_decode_task_end();
							aud_dec_special_effect_stop();
							aud_dec_ramp_down_handle(p_wave_info->nChannels);
							vid_dec_clear_status(C_AUDIO_DECODE_PLAYING);
							vid_dec_end_callback();
							OSQFlush(aud_dec_q);
							dac_audop_speaker_en(0);
						}
					}

					break;
				}
				else
				{
					DBG_PRINT("AudDecGetDataFail\r\n");
					//dac_audop_speaker_en(0);
					
					DBG_PRINT("Not while pfun_decode_one_frame!!!\r\n");
					/*i = 150;
					while(i--)
					{
						cwlen = pfun_decode_one_frame((INT16S *) pcm_addr);
						if((cwlen > 0) || (cwlen < 0) || (vid_dec_get_status() & C_VIDEO_DECODE_ERR))
							break;
						else
						if(cwlen == 0)
							OSTimeDly(1);
					}*/

					if((cwlen <= 0) || (vid_dec_get_status() & C_VIDEO_DECODE_ERR))
					{
						//wait dma done
						DBG_PRINT("GetAudBsFailStop!!!\r\n");
						
						DBG_PRINT("Not while aud_dec_dma_status_get!!!\r\n");
						/*while(aud_dec_dma_status_get())
							OSTimeDly(1);*/

						if(vid_dec_get_status() & C_AUDIO_DECODE_PLAYING)
						{
							audio_decode_task_end();
							aud_dec_special_effect_stop();
							aud_dec_ramp_down_handle(p_wave_info->nChannels);
							vid_dec_clear_status(C_AUDIO_DECODE_PLAYING);
							vid_dec_end_callback();
							OSQFlush(aud_dec_q);
						}
					}
				}
			}
			/*
			else	// Save pcm data to address 0xF00000 (for Debug)  // add by josephhsieh@20170104
			{
				static INT16S *ppp = (INT16S*)(0xF00000);
				INT16S *pcm_local = (INT16S*)pcm_addr;
				INT32S i;
				INT32U len = cwlen;
				DBG_PRINT("len = %d\r\n",len);
				for (i=0;i<len;++i)
				{
					*ppp++ = pcm_local[i];
				}
			}
			*/

			// x2 because DAC output rate would be twice of sample rate if mono audio
			// mp3 is hardware decode, force to 2 channel
			if(p_wave_info->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
				delta_ta[buf_WI] = ((INT64S)p_vid_dec_para->VidTickRate) * cwlen;
			else
			if(p_wave_info->nChannels == 1)
				delta_ta[buf_WI] = ((INT64S) p_vid_dec_para->VidTickRate) * (cwlen << 1);
			else
				delta_ta[buf_WI] = ((INT64S) p_vid_dec_para->VidTickRate) * cwlen;

			if(p_vid_dec_para->upsample_flag)
				delta_ta[buf_WI] >>= 1;

			buf_WI++;
			if(buf_WI >= AUDIO_FRAME_NO)
				buf_WI -= AUDIO_FRAME_NO;
			break;

		case MSG_AUD_DEC_START:
			buf_RI = buf_WI = 0;
			dac_audop_speaker_en(1);
			aud_dec_special_effect_start();
			switch(p_wave_info->wFormatTag)
			{
			case WAVE_FORMAT_PCM:
			case WAVE_FORMAT_MULAW:
			case WAVE_FORMAT_ALAW:
			case WAVE_FORMAT_ADPCM:
			case WAVE_FORMAT_DVI_ADPCM:
				nRet = aud_dec_wave_init();
				pfun_decode_one_frame = aud_dec_wave_one_frame;
				break;

			default:
				do
				{
					DBG_PRINT("[%s, %d]:Wrong wave format\r\n", __func__, __LINE__);
				}
				while(1);
			}

			if(nRet < 0)
				goto AUD_DEC_START_FAIL;
			for(i = 0; i < AUDIO_FRAME_NO; i++)
			{
				pcm_addr = vid_dec_get_next_aud_buffer();
				while(1)
				{
					cwlen = pfun_decode_one_frame((INT16S *) pcm_addr);
					if(cwlen > 0)
						break;
					else
					if(cwlen < 0 || MultiMediaParser_IsEOA(p_vid_dec_para->media_handle))
						goto AUD_DEC_START_FAIL;
					else
						OSTimeDly(1);
				}

				if(p_wave_info->wFormatTag == WAVE_FORMAT_MPEGLAYER3)
					delta_ta[buf_WI] = (INT64S) p_vid_dec_para->VidTickRate * cwlen;
				else
				if(p_wave_info->nChannels == 1)
					delta_ta[buf_WI] = (INT64S) p_vid_dec_para->VidTickRate * (cwlen << 1);
				else
					delta_ta[buf_WI] = (INT64S) p_vid_dec_para->VidTickRate * cwlen;

				if(i == 0)
					aud_dec_double_buffer_put((INT16U *) pcm_addr, cwlen, aud_dec_q);
				else
				if(i == 1)
					aud_dec_double_buffer_set((INT16U *) pcm_addr, cwlen);

				if(p_vid_dec_para->upsample_flag)
					delta_ta[buf_WI] >>= 1;

				buf_WI++;
				if(buf_WI >= AUDIO_FRAME_NO)
					buf_WI -= AUDIO_FRAME_NO;
			}

			OSMboxPost(aud_dec_ack_m, (void *) C_ACK_SUCCESS);
			break;
AUD_DEC_START_FAIL:
			dac_audop_speaker_en(0);
			DBG_PRINT("AudioDecodeStartFail\r\n");
			audio_decode_task_end();
			aud_dec_special_effect_stop();
			OSMboxPost(aud_dec_ack_m, (void *) C_ACK_FAIL);
			break;

		case MSG_AUD_DEC_STOP:
			//while(aud_dec_dma_status_get())	OSTimeDly(1);	//wait dac done
			audio_decode_task_end();
			aud_dec_special_effect_stop();
			aud_dec_ramp_down_handle(p_wave_info->nChannels);
			OSQFlush(aud_dec_q);
			OSMboxPost(aud_dec_ack_m, (void *) C_ACK_SUCCESS);
			break;

		case MSG_AUD_DEC_EXIT:
			#if (Debug_playback == TRUE)
			DBG_PRINT("receive AUD_DEC_EXIT  \r\n");
			#endif
			OSMboxPost(aud_dec_ack_m, (void *) C_ACK_SUCCESS);
			OSTaskDel(OS_PRIO_SELF);
			break;
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////
static INT32S aud_dec_special_effect_start(void)
{
#if VOICE_CHANGER_EN == 1
	INT32S (*pfnVC) (void *, INT16S *, INT32S);
#elif UP_SAMPLE_EN == 1
	INT32S (*pfnUS) (void *, INT16S *, INT32S);
#endif
#if VOICE_CHANGER_EN == 1
	if(p_vid_dec_para->vc_handle == NULL)
	{
		p_vid_dec_para->vc_handle = VoiceChanger_Create();
	}

#elif UP_SAMPLE_EN == 1
	if(p_vid_dec_para->us_handle == NULL)
	{
		p_vid_dec_para->us_handle = UpSample_Create(8192);
	}

#endif
	p_vid_dec_para->upsample_flag = FALSE;
	switch(p_wave_info->wFormatTag)
	{
	case WAVE_FORMAT_PCM:
	case WAVE_FORMAT_MULAW:
	case WAVE_FORMAT_ALAW:
	case WAVE_FORMAT_ADPCM:
	case WAVE_FORMAT_DVI_ADPCM:
#if VOICE_CHANGER_EN == 1
		pfnVC = aud_dec_wave_one_output;
#elif UP_SAMPLE_EN == 1
		pfnUS = aud_dec_wave_one_output;
#endif
		break;
	}

#if VOICE_CHANGER_EN == 1
	if(p_vid_dec_para->vc_handle)
	{
		VoiceChanger_Link(p_vid_dec_para->vc_handle, p_vid_dec_para->work_mem_addr, pfnVC, p_wave_info->nSamplesPerSec, p_wave_info->nChannels);
		VoiceChanger_SetParam(p_vid_dec_para->vc_handle, 12, 12);
		pfnVcOutput = &VoiceChanger_GetOutput;
		p_vid_dec_para->aud_dec_ch_no = VoiceChanger_GetChannel(p_vid_dec_para->vc_handle);
		p_vid_dec_para->aud_dec_sr = VoiceChanger_GetSampleRate(p_vid_dec_para->vc_handle);
	}
	else
	{
		pfnVcOutput = pfnVC;
	}

#elif UP_SAMPLE_EN == 1
	if(p_vid_dec_para->us_handle && (p_wave_info->nSamplesPerSec <= 22050))
	{
		INT8U	channels = 0;
		if(p_wave_info->nChannels == 1)
			channels = 1;
		UpSample_Link(p_vid_dec_para->us_handle, p_vid_dec_para->work_mem_addr, pfnUS, p_wave_info->nSamplesPerSec, p_wave_info->nChannels, 2, channels);
		pfnUsOutput = &UpSample_GetOutput;
		p_vid_dec_para->aud_dec_ch_no = UpSample_GetChannel(p_vid_dec_para->us_handle);
		p_vid_dec_para->aud_dec_sr = UpSample_GetSampleRate(p_vid_dec_para->us_handle);
		p_vid_dec_para->upsample_flag = TRUE;
		DBG_PRINT("AudUpSampleCh = %d\r\n", p_vid_dec_para->aud_dec_ch_no);
		DBG_PRINT("AudUpSampleSR = %d\r\n", p_vid_dec_para->aud_dec_sr);
	}
	else
	{
		pfnUsOutput = pfnUS;
	}

#endif // VOICE_CHANGER_EN == 1
	return STATUS_OK;
}

static void aud_dec_special_effect_stop(void)
{
#if VOICE_CHANGER_EN == 1
	VoiceChanger_Del(p_vid_dec_para->vc_handle);
	p_vid_dec_para->vc_handle = NULL;

#elif UP_SAMPLE_EN
	UpSample_Del(p_vid_dec_para->us_handle);
	p_vid_dec_para->us_handle = NULL;
#endif
}


#if 1     // Skip wav decoder

#define WAV_DEC_BITSTREAM_BUFFER_GAP 64
static INT32U MultiMediaRI = 0;
static INT32S aud_dec_wave_init(void)
{
	INT32U	WI;
	INT32S	nRet;

	nRet = vid_dec_set_aud_dec_work_mem(WAV_DEC_MEMORY_SIZE);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	nRet = vid_dec_set_aud_dec_ring_buffer();
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	MultiMediaRI = 0;
	nRet = wav_dec_init((INT8U *) p_vid_dec_para->work_mem_addr, p_vid_dec_para->ring_buffer_addr);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	//wav_dec_set_ring_buf_size((INT8U *)p_vid_dec_para->work_mem_addr, PARSER_AUD_BITSTREAM_SIZE);
	nRet = wav_dec_set_param((INT8U *) p_vid_dec_para->work_mem_addr, (INT8U *) p_wave_info);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	WI = MultiMediaParser_GetAudRingWI(p_vid_dec_para->media_handle);
	if(!WI)
		RETURN(STATUS_FAIL);

	nRet = STATUS_OK;
Return:
	return nRet;
}

static INT32S aud_dec_wave_one_frame(INT16S *pcm_buffer_addr)
{
	INT32S	nRet = 0;
	INT32U	RI, WI;

	RI = MultiMediaRI;
	WI = MultiMediaParser_GetAudRingWI(p_vid_dec_para->media_handle);
	if (WI > RI)
	{
		if ( (WI-RI)>WAV_DEC_BITSTREAM_BUFFER_GAP )
		{
			INT32U BufferStart = (INT32U)(p_vid_dec_para->ring_buffer_addr) + RI;
			INT32U BufferEnd = (INT32U)(p_vid_dec_para->ring_buffer_addr) + WI - WAV_DEC_BITSTREAM_BUFFER_GAP;
			nRet = BufferEnd - BufferStart;
			gp_memcpy((INT8S*)pcm_buffer_addr, (INT8S*)BufferStart, nRet);
			MultiMediaRI += nRet;
		}
		else		// bitstream not enough
		{
			nRet = 0;
		}
	}
	else
	{
		if ( (WI==0)&&((RI-WI)>WAV_DEC_BITSTREAM_BUFFER_GAP) )
		{
			INT32U BufferStart = (INT32U)(p_vid_dec_para->ring_buffer_addr) + RI;
			INT32U BufferEnd =   (INT32U)(p_vid_dec_para->ring_buffer_addr) + WAV_DEC_BITSTREAM_BUFFER_SIZE - WAV_DEC_BITSTREAM_BUFFER_GAP;
			nRet = BufferEnd - BufferStart;
			gp_memcpy((INT8S*)pcm_buffer_addr, (INT8S*)BufferStart, nRet);
			MultiMediaRI += nRet;
		}
		else if (WI>WAV_DEC_BITSTREAM_BUFFER_GAP+2)
		{
			// 1-st
			INT32U BufferStart = (INT32U)(p_vid_dec_para->ring_buffer_addr) + RI;
			INT32U BufferEnd =   (INT32U)(p_vid_dec_para->ring_buffer_addr) + WAV_DEC_BITSTREAM_BUFFER_SIZE;
			INT32U BufferSize = BufferEnd - BufferStart;
			INT32U pcm_buffer_add_2st;
			gp_memcpy((INT8S*)pcm_buffer_addr, (INT8S*)BufferStart, BufferSize);
			// 2-st
			pcm_buffer_add_2st = (INT32U)pcm_buffer_addr + BufferSize;
			BufferStart = (INT32U)(p_vid_dec_para->ring_buffer_addr);
			BufferEnd = (INT32U)(p_vid_dec_para->ring_buffer_addr) + WI - WAV_DEC_BITSTREAM_BUFFER_GAP;
			nRet = BufferEnd - BufferStart;
			gp_memcpy((INT8S*)pcm_buffer_add_2st, (INT8S*)BufferStart, nRet);
			MultiMediaRI = nRet;
			nRet += BufferSize;
		}
		else
		{
			nRet = 0;
		}
	}



	RI = MultiMediaRI;
	MultiMediaParser_RefillAudBuf(p_vid_dec_para->media_handle, RI);

	if ( (nRet&0x1)!=0 )
	{
		DBG_PRINT("Warning!! POP noise\r\n");
	}

	return (nRet>>1);		// 1 sample = 2 bytes
							// Skip last "WAV_DEC_BITSTREAM_BUFFER_GAP" bytes data.
}


#else		// original flow


static INT32S aud_dec_wave_init(void)
{
	INT32U	WI;
	INT32S	nRet;

	nRet = vid_dec_set_aud_dec_work_mem(WAV_DEC_MEMORY_SIZE);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	nRet = vid_dec_set_aud_dec_ring_buffer();
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	nRet = wav_dec_init((INT8U *) p_vid_dec_para->work_mem_addr, p_vid_dec_para->ring_buffer_addr);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	//wav_dec_set_ring_buf_size((INT8U *)p_vid_dec_para->work_mem_addr, PARSER_AUD_BITSTREAM_SIZE);
	nRet = wav_dec_set_param((INT8U *) p_vid_dec_para->work_mem_addr, (INT8U *) p_wave_info);
	if(nRet < 0)
		RETURN(STATUS_FAIL);

	WI = MultiMediaParser_GetAudRingWI(p_vid_dec_para->media_handle);
	if(!WI)
		RETURN(STATUS_FAIL);

	nRet = STATUS_OK;
Return:
	return nRet;
}


static INT32S aud_dec_wave_one_frame(INT16S *pcm_buffer_addr)
{
#if VOICE_CHANGER_EN == 1
	INT32S	nRet;
	INT32U	RI;

	nRet = pfnVcOutput(p_vid_dec_para->vc_handle, pcm_buffer_addr, WAV_DEC_FRAMESIZE);	//pcm_point*2
	if(nRet <= 0)
		RETURN(nRet);;

#elif UP_SAMPLE_EN == 1
	INT32S	nRet;
	INT32U	RI;

	nRet = pfnUsOutput(p_vid_dec_para->us_handle, pcm_buffer_addr, WAV_DEC_FRAMESIZE);	//pcm_point*2
	if(nRet <= 0)
		RETURN(nRet);

#else
	INT32S	nRet;
	INT32U	RI;

	nRet = aud_dec_wave_one_output(p_vid_dec_para->work_mem_addr, pcm_buffer_addr, WAV_DEC_FRAMESIZE);
	if(nRet <= 0)
		RETURN(nRet);
#endif // VOICE_CHANGER_EN == 1
	Return : RI = wav_dec_get_ri((INT8U *) p_vid_dec_para->work_mem_addr);
	MultiMediaParser_RefillAudBuf(p_vid_dec_para->media_handle, RI);
	return nRet;
}

static INT32S aud_dec_wave_one_output(void *work_mem, INT16S *pcm_buffer_addr, INT32S maxlen)
{
	INT32S	pcm_point;
	INT32U	RI, WI;
	INT32S	nRet, size;

	WI = MultiMediaParser_GetAudRingWI(p_vid_dec_para->media_handle);
	RI = wav_dec_get_ri((INT8U *) p_vid_dec_para->work_mem_addr);

	size = WI - RI;
	if(size == 0)
		RETURN(0);
	if(size < 0)
		size += PARSER_AUD_BITSTREAM_SIZE;

	//fix wave decode library
	if (0)
	{
		DBG_PRINT("Add something.\r\n");
	}
	else if((p_wave_info->wFormatTag == WAVE_FORMAT_ADPCM || p_wave_info->wFormatTag == WAVE_FORMAT_DVI_ADPCM) && (p_wave_info->nChannels == 0x02))
	{
		if(size < PARSER_AUD_BITSTREAM_SIZE >> 1 && !MultiMediaParser_IsEOA(p_vid_dec_para->media_handle))
			RETURN(0);
	}
	else
	{
		if(size < PARSER_AUD_BITSTREAM_SIZE >> 5 && !MultiMediaParser_IsEOA(p_vid_dec_para->media_handle))
			RETURN(0);
	}


	//limite the wave length is less 128ms to match  p_vid_dec_para->time_range
	if(wav_dec_get_SampleRate((INT8U *) p_vid_dec_para->work_mem_addr) < 16000)
	{
		if(size >= PARSER_AUD_BITSTREAM_SIZE / 4)
		{
			WI = RI + PARSER_AUD_BITSTREAM_SIZE / 4;
			if(WI > PARSER_AUD_BITSTREAM_SIZE)
				WI -= PARSER_AUD_BITSTREAM_SIZE;
		}
	}

	pcm_point = wav_dec_run((INT8U *) p_vid_dec_para->work_mem_addr, (INT16S *) pcm_buffer_addr, WI);
	if(pcm_point < 0)
		RETURN(pcm_point);
	nRet = pcm_point * wav_dec_get_nChannels((INT8U *) p_vid_dec_para->work_mem_addr);

#if UP_SAMPLE_EN == 1
	if(p_vid_dec_para->upsample_flag)
		nRet = pcm_point * UpSample_GetChannel(p_vid_dec_para->us_handle);
#endif
	Return : return nRet;
}


#endif

/////////////////////////////////////////////////////////////////////////////////////////
